﻿using Gma.System.MouseKeyHook;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace AutoRevit.Tool;

/// <summary>
/// 选择时的钩子工具
/// </summary>
public class HookSelectionOperation : IDisposable
{
    /// <summary>
    /// 键盘处理
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <returns></returns>
    public delegate bool KeyHandler(object? sender, KeyEventArgs e);

    /// <summary>
    /// 鼠标处理
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <returns></returns>
    public delegate bool MouseExtHandler(object? sender, MouseEventExtArgs e);

    #region 外部函数

    private delegate bool CallBack(IntPtr hwnd, int lParam);

    [DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
    private static extern bool EnumChildWindows(IntPtr hwndParent, CallBack lpEnumFunc, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32.dll", EntryPoint = "SendMessageA")]
    private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);

    [DllImport("user32.dll")]
    private static extern IntPtr SetActiveWindow(IntPtr hwnd);

    #endregion 外部函数

    private readonly IKeyboardMouseEvents _events;

    private readonly IDictionary<KeyHandler, bool> _keyHandlerMap;

    private readonly IDictionary<MouseExtHandler, bool> _mouseExtHandlerMap;

    private bool isStarted = false;

    /// <summary>
    /// 实例化
    /// </summary>
    public HookSelectionOperation()
    {
        _events = Hook.AppEvents();

        _keyHandlerMap = new Dictionary<KeyHandler, bool>();
        _mouseExtHandlerMap = new Dictionary<MouseExtHandler, bool>();
    }

    /// <summary>
    /// 启动
    /// </summary>
    public HookSelectionOperation Start()
    {
        if (isStarted)
        {
            return this;
        }

        isStarted = true;

        _events.MouseDownExt += Events_MouseDownExt;
        _events.MouseUpExt += Events_MouseUpExt;
        _events.KeyDown += Events_KeyDown;
        _events.KeyUp += Events_KeyUp;

        return this;
    }

    /// <summary>
    /// 关闭
    /// </summary>
    public void Close()
    {
        isStarted = false;

        _events.MouseDownExt -= Events_MouseDownExt;
        _events.MouseUpExt -= Events_MouseUpExt;
        _events.KeyDown -= Events_KeyDown;
        _events.KeyUp -= Events_KeyUp;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="keyHandle"></param>
    /// <param name="isDown">是否按下,反之为弹起</param>
    /// <returns></returns>
    public HookSelectionOperation AddKeyHandler(KeyHandler keyHandle, bool isDown)
    {
        _keyHandlerMap.Add(keyHandle, isDown);
        return this;
    }

    /// <summary>
    /// 添加鼠标按下处理
    /// </summary>
    /// <param name="mouseExtHandler"></param>
    /// <param name="isDown">是否按下</param>
    public HookSelectionOperation AddMouseHandler(MouseExtHandler mouseExtHandler, bool isDown)
    {
        _mouseExtHandlerMap.Add(mouseExtHandler, isDown);
        return this;
    }

    /// <summary>
    /// 处理释放，需要
    /// </summary>
    public void Dispose()
    {
        _events.Dispose();
    }

    private void Events_KeyUp(object? sender, KeyEventArgs e)
    {
        foreach (var item in _keyHandlerMap)
        {
            if (item.Key(sender, e))
            {
                if (!item.Value)
                {
                    Task.Run(Finish);
                }
                e.Handled = true;
            }
        }
    }

    private void Events_KeyDown(object? sender, KeyEventArgs e)
    {
        foreach (var item in _keyHandlerMap)
        {
            if (item.Key(sender, e))
            {
                if (item.Value)
                {
                    Task.Run(Finish);
                }
                e.Handled = true;
            }
        }
    }

    private void Events_MouseUpExt(object? sender, MouseEventExtArgs e)
    {
        foreach (var item in _mouseExtHandlerMap)
        {
            if (item.Key(sender, e))
            {
                if (!item.Value)
                {
                    Task.Run(Finish);
                }
                e.Handled = true;
            }
        }
    }

    private void Events_MouseDownExt(object? sender, MouseEventExtArgs e)
    {
        foreach (var item in _mouseExtHandlerMap)
        {
            if (item.Key(sender, e))
            {
                if (item.Value)
                {
                    Task.Run(Finish);
                }
                e.Handled = true;
            }
        }
    }

    /// <summary>
    /// 模拟按下“完成”按钮
    /// </summary>
    public static void Finish()
    {
        var rvtwindowIntPtr = Autodesk.Windows.ComponentManager.ApplicationWindow;

        var finishIntPtr = IntPtr.Zero;

        _ = EnumChildWindows(rvtwindowIntPtr,
                   (hwnd, l) =>
                   {
                       StringBuilder windowText = new StringBuilder(200);
                       StringBuilder className = new StringBuilder(200);

                       GetWindowText(hwnd, windowText, windowText.Capacity);

                       GetClassName(hwnd, className, className.Capacity);

                       if ((windowText.ToString().Equals("完成", StringComparison.Ordinal) ||
                           windowText.ToString().Equals("Finish", StringComparison.Ordinal)) &&
                           className.ToString().Contains("Button"))
                       {
                           finishIntPtr = hwnd;
                           return false;
                       }
                       return true;
                   }, IntPtr.Zero);

        SendMessage(finishIntPtr, 245, 0, 0);

        SetActiveWindow(rvtwindowIntPtr);
    }
}
